package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.mapper.UserPaidTrackMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;
	@Autowired
	private WxMaService wxMaService;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private RedisTemplate redisTemplate;

	/**
	 * 提供给小程序微信登录接口
	 * @param code 小程序集成SDK后获取临时票据(基于当前微信用户产生的)
	 * @return
	 */
	@Override
	public Map<String, String> wxLogin(String code) {
		try {
			//1.根据小程序提交code再加appid+appsecret获取微信账户唯一标识:wxOpenId
			WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
			String wxOpenid = sessionInfo.getOpenid();
			if (StringUtils.isBlank(wxOpenid)) {
				throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
			}
			//2.根据微信唯一标识查询用户记录
			LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(UserInfo::getWxOpenId,wxOpenid);
			UserInfo userInfo = userInfoMapper.selectOne(wrapper);
			//3.判断用户记录是否存在(用户是否绑定过该微信账号)
			if (userInfo == null) {
				//如果不存在,新增用户记录绑定微信账户唯一标识,隐式初始化账户记录
				//3.1 构建保存用户信息记录绑定微信唯一标识
				userInfo = new UserInfo();
				userInfo.setWxOpenId(wxOpenid);
				userInfo.setNickname("听友"+ IdUtil.getSnowflakeNextId());
				userInfo.setAvatarUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/hFKeRpRQU4wG…axvke5nueicggowdBricR4pspWbp6dwFtLSCWJKyZGJoQ/132");
				userInfoMapper.insert(userInfo);
				//3.2 隐式初始化账户记录
				//3.2.1 构建初始化对象所需参数对象
				Map<String, Object> mapData = new HashMap<>();
				mapData.put("userId",userInfo.getId());
				mapData.put("title","首次登录赠送体验金");
				mapData.put("amount",new BigDecimal("10"));
				mapData.put("orderNo","zs" + IdUtil.getSnowflakeNextIdStr());
				//3.2.2 调用发送消息工具类方法发送消息
				rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_USER_REGISTER,mapData);
			}
			//4.为用户生成令牌存入Redis,其中Redis中key=前缀+token  value=用户基本信息UserInfoVo
			//4.1 生成token值
			String token = IdUtil.randomUUID();
			//4.2 构建用户登录key, 形式=user:login:token值
			String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
			//4.3 将用户登录信息UserInfoVo存入Redis
			UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
			redisTemplate.opsForValue().set(loginKey,userInfoVo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
			//5.封装token到对象响应给前端
			Map<String, String> map = new HashMap<>();
			map.put("token",token);
			return map;
		} catch (Exception e) {
			log.error("[用户服务]微信登录接口异常：{}", e);
			throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
		}
	}

	/**
	 * 根据用户id获取用户信息
	 * @param userId
	 * @return
	 */
	@Override
	public UserInfoVo getUserInfo(Long userId) {
		UserInfo userInfo = userInfoMapper.selectById(userId);
		if (userInfo != null) {
			UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo,UserInfoVo.class);
			return userInfoVo;
		}
		return null;
	}

	/**
	 * 更新用户基本信息（昵称、头像）
	 * @param userId
	 * @param userInfoVo
	 */
	@Override
	public void updateUser(Long userId, UserInfoVo userInfoVo) {
		UserInfo userInfo = new UserInfo();
		userInfo.setId(userId);
		userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
		userInfo.setNickname(userInfoVo.getNickname());
		userInfoMapper.updateById(userInfo);
	}


	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;
	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	/**
	 * 检查提交声音ID列表购买情况
	 * @param userId
	 * @param albumId
	 * @param needCheckBuyStateTrackIds
	 * @return 提交待检查购买情况，声音ID购买结果 {38679:1,38678:0}
	 */
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long userId, Long albumId, List<Long> needCheckBuyStateTrackIds) {
		Map<Long, Integer> map = new HashMap<>();
		//检查提交声音ID列表购买情况
		//1.根据用户id+专辑id查询 专辑 购买记录
		LambdaQueryWrapper<UserPaidAlbum> userPaidAlbumLambdaQueryWrapper = new LambdaQueryWrapper<>();
		userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getAlbumId,albumId);
		userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getUserId,userId);
		Long count = userPaidAlbumMapper.selectCount(userPaidAlbumLambdaQueryWrapper);
		//1.1 存在购买记录
		if (count > 0) {
			for (Long needCheckBuyStateTrackId : needCheckBuyStateTrackIds) {
				//1.1 将所有提交的待检查声音id购买情况设为1
				map.put(needCheckBuyStateTrackId,1);
			}
			return map;
		}

		//2.根据用户id+专辑id查询已购 声音 列表
		LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidTrack::getUserId,userId);
		wrapper.eq(UserPaidTrack::getAlbumId,albumId);
		wrapper.select(UserPaidTrack::getTrackId);
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
		if (CollectionUtil.isEmpty(userPaidTrackList)) {
			//2.1 如果不存在已购声音,将所有提交的待检查声音id购买情况设置0返回
			for (Long needCheckBuyStateTrackId : needCheckBuyStateTrackIds) {
				map.put(needCheckBuyStateTrackId,0);
			}
			return map;
		}
		//2.2 如果已购声音,遍历待检查的声音id列表判断找出已购声音,将其购买情况设置为1,未购买声音购买情况设置为0
		List<Long> userPaidTrackIdList = userPaidTrackList
				.stream()
				.map(UserPaidTrack::getTrackId)
				.collect(Collectors.toList());
		for (Long needCheckBuyStateTrackId : needCheckBuyStateTrackIds) {
			//判断已购声音id列表中是否存在待检查声音id
			if (userPaidTrackIdList.contains(needCheckBuyStateTrackId)) {
				map.put(needCheckBuyStateTrackId,1);
			} else {
				map.put(needCheckBuyStateTrackId,0);
			}
		}
		return map;
	}

	/**
	 * 查询用户某个专辑已购声音ID列表
	 * @param userId
	 * @param albumId
	 * @return 已购声音id列表
	 */
	@Override
	public List<Long> getUserPaidTrackIdList(Long userId, Long albumId) {
		LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidTrack::getUserId,userId);
		wrapper.eq(UserPaidTrack::getAlbumId,albumId);
		//只需要获取已购声音id
		wrapper.select(UserPaidTrack::getTrackId);
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
		if (CollectionUtil.isNotEmpty(userPaidTrackList)) {
			List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId)
					.collect(Collectors.toList());
			return userPaidTrackIdList;
		}
		return null;
	}

	/**
	 * 查询当前用户是否购买过指定专辑
	 * @param albumId
	 * @return
	 */
	@Override
	public Boolean isPaidAlbum(Long albumId) {
		Long userId = AuthContextHolder.getUserId();
		LambdaQueryWrapper<UserPaidAlbum> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidAlbum::getUserId,userId);
		wrapper.eq(UserPaidAlbum::getAlbumId,albumId);
		return userPaidAlbumMapper.selectCount(wrapper) > 0;
	}
}
